package org.anyline.simple.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import com.zaxxer.hikari.HikariDataSource;
import com.zaxxer.hikari.HikariPoolMXBean;
import org.anyline.data.datasource.DataSourceMonitor;
import org.anyline.data.runtime.DataRuntime;
import org.anyline.exception.DataSourceUsingException;
import org.springframework.stereotype.Component;

@Component
public class DefaultMonitor implements DataSourceMonitor {

    /**
     * 注销数据源之前会调用
     * @param key 数据源名称
     * @param datasource 数据源
     * @return  0:当前方法内未释放 需要上层继续操作,如调用datasource.close()  1:当前方法内已释放 不需要上层继续操作
     * @throws DataSourceUsingException 如果抛出异常，上层方法会抛出异常并中断注销
     */
    @Override
    public int destroy(DataRuntime runtime, String key, Object datasource) throws DataSourceUsingException {
        if(datasource instanceof HikariDataSource){
            HikariDataSource ds = (HikariDataSource)datasource;
            HikariPoolMXBean mx = ds.getHikariPoolMXBean();
            if(null != mx) {
                int active = mx.getActiveConnections();
                if (active > 0) {
                    throw new DataSourceUsingException(key, datasource);
                }
            }
            ds.close();
        }else if(datasource instanceof DruidDataSource){
            DruidDataSource ds = (DruidDataSource)datasource;
            int active = ds.getActiveCount();
            if(active > 0){
                int cnt = 0;
                while (active > 0){
                    if(cnt ++ > 10){
                        throw new DataSourceUsingException(key, datasource);
                    }
                    try{
                        Thread.sleep(100);
                    }catch (Exception ignore){

                    }
                    active = ds.getActiveCount();
                }
            }
            ds.close();
        }
        return 0;
    }
}
